#include "bib_Log.h"
#include "bib_Abrir_Configuracion.h"
#include "bib_Socket.h"
#include "bib_Disco.h"
#include "bib_Hilo_Principal.h"

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>

char nivelLog;
char modoInicio;

struct EST_DISCO disco;
struct EST_CHS poscicionCabezal;

struct EST_PEDIDOS *primerPedido;
struct EST_PEDIDOS *ultimoPedido;

pthread_mutex_t mutexLog;
pthread_mutex_t mutexCola;
pthread_mutex_t mutexSocket;

int sockExterior;
int sockConsola;

char flagFin;

char *persistencia;
uint32_t cantEscrituras;
size_t tamanio;

int main(void){

	struct CONFIG_EST config;
	int sockEscuchaConsola;
	int sockMax;
	fd_set sockets;
	fd_set socketsListosLeer;
	struct sockaddr address;
	char flagConsola;
	int i;
	pthread_t hilo;
	int archPersistencia;

	if (crearMutexLog())
		return FIN_ERROR;

	if (abrirConfiguracion(&config))
		return FIN_ERROR;

	establecerConexionExterior(&config);

	sockConsola = 0;

	if (!abrirSocketUnix(&sockEscuchaConsola)){
		if ((flagConsola = crearHijoConsola()) == FIN_ERROR){
			cerrarSocket(&sockEscuchaConsola);
			cerrarSocket(&sockExterior);
			return FIN_ERROR;
		}

		if (flagConsola == FIN_OK){
			struct HEADER_NIPC header;

			if (aceptarConexion(&sockEscuchaConsola, &sockConsola, &address))
				sockConsola = 0;

			else{
				header.type = TIPO_HANDSHAKE;
				header.payloadLength = sizeof(struct EST_CHS);

				if (enviarMensajeNIPC(sockConsola, &header, (char *) &disco.chs))
					cerrarSocket(&sockConsola);
			}
		}

		cerrarSocket(&sockEscuchaConsola);
	}

	if (inicializarVariables(&sockMax, &sockets)){
		cerrarSocket(&sockExterior);
		cerrarSocket(&sockConsola);
		return FIN_ERROR;
	}

	if (crearHiloAtencionPedidos(&hilo)){
		cerrarSocket(&sockExterior);
		cerrarSocket(&sockConsola);
		return FIN_ERROR;
	}

	if (abrirMapearArchivoPersistencia(config.archivoPersistencia, &archPersistencia)){
		cerrarSocket(&sockExterior);
		cerrarSocket(&sockConsola);
		return FIN_ERROR;
	}

	while ((sockConsola || sockExterior) && flagFin){

		socketsListosLeer = sockets;

		if (verificarDescriptores(sockMax, &socketsListosLeer)) /*select*/
			return FIN_ERROR;

		for (i = 0; i <= sockMax; i++)
			if (FD_ISSET(i, &socketsListosLeer))
				recibirPedido(i, &sockets, &sockMax);
	}

	finalizarPrograma(hilo, archPersistencia);

	return FIN_OK;
}
